home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 1 Issue 2
/
PDCD-1 - Issue 02.iso
/
_editors
/
editors
/
_stronged
/
!EXTHELP
/
HEAP
< prev
next >
Wrap
Text File
|
1993-04-12
|
12KB
|
402 lines
Heap memory manager
===================
WimpExtension's heap manager is one of the module's most powerful, useful,
and - unavoidably - complicated features. This document is provided to
explain more about what a relocatable heap is, and how to use it.
Programming examples in this document are given in BASIC, because practically
everyone knows how to use it.
This document assumes that you know how to program in the RISC OS Wimp, and
that you understand terms such as "WimpSlot" (read the chapter "The Window
Manager" in the PRMs if you don't).
Read the "SWIs" and "Manual" files for a brief description of the parameters
for the SWI WimpExt_Heap.
Why do I need a heap?
---------------------
Any program which uses more than one block of memory which changes size needs
a heap manager. For example, Edit and Paint need a heap manager, because they
can have several files loaded at once, all of which can be changing size at
any time. The files are loaded into memory "blocks", which are provided by
the heap manager.
Why use a relocatable heap?
---------------------------
RISC OS provides a non-relocatable heap manager. This means that the memory
blocks are fixed in memory, and don't move about. The problem with this is
that it gets very wasteful on memory when you have finished using the block.
Say you loaded three files into a text editor:
/--------\ Highest memory address
| File 3 |
| |
|--------|
| File 2 |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
This is fine, no problems so far. However, suppose the user decided the close
the file "File 2":
/--------\ Highest memory address
| File 3 |
| |
|--------|
| unused |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
The block of memory in the middle is now unused, and is wasting space. A
non-relocatable heap manager can't do anything about this. Another example is
if the user adds something to File 2, making it longer. File 2 will no longer
fit in its original block - if you extended it then it would overwrite
File 3. Therefore the heap manager has to copy the whole file up in memory,
as shown in the diagram:
/--------\ Highest memory address
| File 2 |
| |
| |
| |
|--------|
| File 3 |
| |
|--------|
| unused |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
WimpExtension provides a relocatable heap manager, however. This means that
the heap manager is allowed to move the blocks about, to try and reduce the
amount of wasted memory. In the situation above, for example, WimpExtension
would move File 2 and File 3 down in memory, like so:
/--------\ Highest memory address
| File 2 |
| |
| |
| |
|--------|
| File 3 |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
As you can see, this can save a lot of memory.
Anchors
-------
The only disadvantage of a reloctable heap is due to the fact that it IS
relocatable - the blocks of memory aren't fixed and may move about. A
question which immediately arises is "How do I find my memory block?" - if
the block may have moved, how do you find it?
The answer is by using an "anchor". An anchor is a word in memory. The
contents of this word is always a pointer to the start of the block. ie:
/-------\
| |
/--------\ | |
| anchor |--------->| block |
\--------/ \-------/
The anchor always stays fixed in the same place in memory, so you always know
where to find it. So, to find the location of your block, you would use:
block%=!anchor% : REM block% now points to the first byte in the block
The anchors are stored all together at the beginning of the heap.
Size of blocks
--------------
The word before the start of any block contains the size of the block in
bytes. So to find the size of a block, you would use:
size%=!(block%-4)
or:
size%=!( (!anchor%) -4)
(because block%=!anchor%).
Due to the way the heap manager works, the size of a block is always four
plus a multiple of eight (ie. 12, 20, 28, etc.). If you ask WimpExtension to
make a block with a size which isn't four plus a multiple of eight, then the
size will be rounded up by between one and seven bytes, to take it to the
next largest acceptable size.
Initialising the heap
---------------------
Before you can use any of the heap operations, you must initialise the heap.
This requires two parameters - the number of anchors to create initially, and
the address in memory of the base of the heap.
The anchors are stored all together at the beginning of the heap. Because you
need one anchor for every block in use, the number of anchors is effectively
the maximum number of blocks you can have in use at any one time. You can
create more anchors later, but it is best to create enough now, and then you
don't have to worry about it later. Remember that anchors do take memory
though, so don't go wild.
For example:
SYS "WimpExt_Heap",0,base%,anchors%
Note that a heap which is empty (ie. no blocks are in use) takes absolutely
no memory at all.
Allocating blocks
-----------------
Whenever you ask WimpExtension to make you a new block (called "allocating" a
block), it gives you a pointer to the anchor for that block. You must store
the pointer to the anchor, NOT the pointer to the block, because the anchor
will never move, but the block may do. For example, to ask WimpExtension for
a block "size%" bytes long, you would use:
SYS "WimpExt_Heap",2,,size% TO ,anchor%
If WimpExtension cannot create the block, because there is not enough free
memory, then the anchor returned will be zero. You need to check for this
before writing anything into the block. eg:
SYS "WimpExt_Heap",2,,size% TO ,anchor%
IF anchor%=0 THEN ERROR 1,"Not enough free memory"
Freeing blocks
--------------
When you have finished using a block, you use the "Free block" call to tell
WimpExtension that you don't need the block any more, and the memory it takes
up can be re-used. eg:
SYS "WimpExt_Heap",3,anchor%
or:
SYS "WimpExt_Heap",3,block%
The block will be added to WimpExtension's list of free blocks.
Reallocating blocks
-------------------
Sometimes you will want to re-size a block - this is called "reallocating"
the block. WimpExtension allows you to increase or decrease the size of any
block at any time. eg:
SYS "WimpExt_Heap",4,block%,new_size% TO ,flag%
or:
SYS "WimpExt_Heap",4,anchor%,new_size% TO ,flag%
If the flag is zero on exit then the re-size failed because there wasn't
enough free memory.
Note that this call may cause the specified block to move in memory. Only the
specific block that you are re-sizing can move, though - all the other blocks
will stay where they are.
Garbarge collection
-------------------
"Garbage collection" is the whole point of the relocatable heap. This is the
process of shuffling the blocks about in memory, so that no memory is wasted.
For example, if the heap was in the following state:
/---------\ Highest memory address
| block 2 |
| |
|---------|
| free |
| |
| |
|---------|
| block 1 |
\---------/ Lowest memory address
then performing garbage collection would shuffle the blocks as follows:
/---------\ Highest memory address
| block 2 |
| |
|---------|
| block 1 |
\---------/ Lowest memory address
This then allows WimpExtension to decrease your task's WimpSlot, thus making
this memory available to any other programs which might need it.
Two garbage collection calls are provided; the Tidy call:
SYS "WimpExt_Heap",5
and the Compact call:
SYS "WimpExt_Heap",6
The Tidy call just tidies the heap a little bit - the heap won't necessarily
immediately be shuffled into the ideal position, but the call is usually
quite fast. This call is intended to be called just before you call
Wimp_Poll. If you set bit 3 of R2 when you called WimpExt_Initialise, then
the heap will be automatically Tidied once a second, in WimpExt_PrePoll. Most
of the time, you can just set this bit, and then forget all about garbage
collection - it will all be handled for you.
The Compact call tidies the heap completely - the heap will immediately be
shuffled into the ideal position. This call is often slower than the Tidy
call, however, as it does more work.
How often should I tidy the heap?
---------------------------------
How often you tidy the heap depends on the average size of the blocks your
program uses. If your program uses lots of little blocks then you should tidy
the heap quite often. If it uses a smaller number of larger blocks then you
should tidy it less often.
For a text editor, for example, the once-a-second tidy provided automatically
should be fine. For something which uses smaller blocks, you should probably
tidy the heap more often.
Finding the anchor of a block
-----------------------------
If you have a pointer to a block, and you want to locate the block's anchor,
then a call is provided to do this:
SYS "WimpExt_Heap",7,block% TO ,anchor%
An error is produced if block% is not a valid pointer to the start of a
block.
Fixing blocks
-------------
Sometimes you may want to temporarily 'fix' the heap. This makes it so that
all the blocks are fixed and cannot move. This is useful if you need to rely
on a block staying put at the same position in memory for a while.
To fix the heap, you would use:
SYS "WimpExt_Heap",8
and to unfix it you would use:
SYS "WimpExt_Heap",10
Note that WimpExtension keeps a count of the number of times you haved fixed
the heap, and only unfixes the heap when you tell it to the same number of
times. ie:
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",10
would leave the heap fixed. The following, however, would leave the heap
unfixed, as the number of "unfixings" matches the number of "fixings":
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",10
SYS "WimpExt_Heap",10
You can force WimpExtension to unfix the heap straight away, regardless of
the number of times it has been fixed, using the following call:
SYS "WimpExt_Heap",9
ie. The following would leave the heap unfixed:
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",8
SYS "WimpExt_Heap",9
Creating more anchors
---------------------
WimpExtension allows you to create more anchors, even while the heap is in
use. Note that this call has to move the entire heap up in memory, so it can
be quite slow. For example:
SYS "WimpExt_Heap",11,add%
"add%" extra anchors will be created. All the blocks will be moved.
WimpExtension also provides a call to allocate a block, automatically
creating more anchors if you've run out:
SYS "WimpExt_Heap",12,,size% TO ,anchor%
Freeing all blocks
------------------
WimpExtension provides a call to free all the blocks in the heap:
SYS "WimpExt_Heap",13
Every single allocated block will be freed, and all the memory released.
Describing the heap
-------------------
WimpExtension provides a call which provides various bits of information
about the heap:
SYS "WimpExt_Heap",1 TO ,,largest%,free%,heapsize%,anchors%,blocks%
largest% : The size of the largest continuous area of memory in the heap
free% : The total amount of memory free in the heap
heapsize% : The total amount of memory used by the heap
anchors% : The number of anchors which have been created
blocks% : The number of blocks which are currently allocated